package sk.gtug.pivoplus.malepivo;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import sk.gtug.pivoplus.malepivo.map.PubLocations;
import sk.gtug.pivoplus.malepivo.utils.Http;
import sk.gtug.pivoplus.malepivo.utils.LocationHelper;
import sk.gtug.pivoplus.malepivo.widget.AddressSearchView;
import sk.gtug.pivoplus.server.domain.twig.TwigKrcmicka;
import sk.m217.actionbarcompat.ActionBarCompat;
import sk.m217.actionbarcompat.MenuItemCompat;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Address;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class MapSearchActivity extends ActionBarMapActivity {

	private static final String TAG = "MapSearchActivity";
	private Menu mMenu;
	private MapView mMapView;
	private LocationHelper mLocationHelper;
	private MapController mController;
	private MyLocationOverlay mLocationOverlay;

	private PubLocations mPubLocations;
	private AddressSearchView mAddressSearchView;
	private SharedPreferences mPrefs;

	// Keys used with onSaveInstanceState()
	private static final String KEY_MAPCENTER = "map_center";
	private static final String KEY_ZOOMLEVEL = "zoom_level";
	private static final String KEY_SATELLITE = "is_satellite";

	private ProgressDialog mProgressDialog = null;
	private boolean mFirstFix = true;

	@Override
    public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.map_search);
		// setting up action bar
		getActionBarHelper().initActionBar();
		ActionBarCompat.setDisplayHomeAsUpEnabled(this, true);

		/*
		// docasne TODO
		SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
		SharedPreferences.Editor editor = preferences.edit();
		editor.putString(Application.PREFS_KEY_CITY, "Bratislava");
		editor.commit();
		*/

		mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
		mLocationHelper = new LocationHelper(this);
		mLocationHelper.updateLocation();

		mMapView = (MapView) findViewById(R.id.map);
		mMapView.setBuiltInZoomControls(true);
		mController = mMapView.getController();
		mController.setZoom(16);

		mLocationOverlay = new MyLocationOverlay(this, mMapView);
		mMapView.getOverlays().add(mLocationOverlay);

		mPubLocations = new PubLocations(mMapView);
		mMapView.getOverlays().add(mPubLocations);
		mMapView.postInvalidate();

		final ArrayList<TwigKrcmicka> mPubs = new ArrayList<TwigKrcmicka>();

		Runnable runnable = new Runnable() {
			public void run() {
				// get pubs
				Type listType = new TypeToken<List<TwigKrcmicka>>() {}.getType();
				String result = Http.get("http://pluspivo.appspot.com/pivo-plus-rest/pivo/krcmy");
				List<TwigKrcmicka> pubs = new Gson().fromJson(result, listType);
				try {
					mPubs.addAll(pubs);
					Log.w("TAG", "size(): " + mPubs.size());
				} catch (Exception e) {
					Log.w("TAG", e.getMessage());
				}
				runOnUiThread(new Runnable() {
					public void run() {
						for (TwigKrcmicka pub : mPubs) {
							mPubLocations.addPub(pub);
						}
					}
				});
			}
		};
		new Thread(runnable).start();
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	@Override
	public void onResume() {
		super.onResume();
		mLocationOverlay.enableMyLocation();
		mLocationOverlay.enableCompass();
		if (mFirstFix) {
			mLocationOverlay.runOnFirstFix(new Runnable() {
				public void run() {
					mController.animateTo(mLocationOverlay.getMyLocation());
					mFirstFix = false;
				}
			});
		}
	}

	@Override
	public void onPause() {
		super.onPause();
		mLocationOverlay.disableMyLocation();
		mLocationOverlay.disableCompass();
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		GeoPoint mapCenter = mMapView.getMapCenter();
		outState.putIntArray(KEY_MAPCENTER, new int[] {mapCenter.getLatitudeE6(),
				mapCenter.getLongitudeE6()});
		outState.putInt(KEY_ZOOMLEVEL, mMapView.getZoomLevel());
		outState.putBoolean(KEY_SATELLITE, mMapView.isSatellite());
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);
		int[] coords = savedInstanceState.getIntArray(KEY_MAPCENTER);
		mController.setZoom(savedInstanceState.getInt(KEY_ZOOMLEVEL));
		mMapView.setSatellite(savedInstanceState.getBoolean(KEY_SATELLITE));
		GeoPoint mapCenter = new GeoPoint(coords[0], coords[1]);
		mController.setCenter(mapCenter);
		mFirstFix = false;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater menuInflater = getMenuInflater();
		menuInflater.inflate(R.menu.map_options, menu);
		if (mMenu != null) {
			return super.onCreateOptionsMenu(menu);
		}
		mMenu = menu;
		MenuItem item = mMenu.findItem(R.id.menu_search);
		MenuItemCompat.setOnActionExpandListener(item,
				new MenuItemCompat.OnActionExpandListenerCompat() {
       		@Override
       		public boolean onMenuItemActionExpand(MenuItem item) {
       			//mMenu.findItem(R.id.menu_viewmode).setVisible(false);
       			mMenu.findItem(R.id.menu_mylocation).setVisible(false);
       			return true;
       		}
       		@Override
       		public boolean onMenuItemActionCollapse(MenuItem item) {
       			//mMenu.findItem(R.id.menu_viewmode).setVisible(true);
       			mMenu.findItem(R.id.menu_mylocation).setVisible(true);
       			mAddressSearchView.hideSoftKeyboard();
       			return true;
       		}
		});

		mAddressSearchView = (AddressSearchView) MenuItemCompat.getActionView(item);
		mAddressSearchView.setAddressSearchListener(new AddressSearchView.AddressSearchListener() {
			@Override
			public void onAddressSearchResult(Address address) {
				if (address != null) {
					navigateTo(address);
				} else {
					Toast.makeText(MapSearchActivity.this, R.string.address_not_found,
							Toast.LENGTH_SHORT).show();
				}
			}
			@Override
			public void onAddressSearchEnd() {
				if (mProgressDialog != null) {
					mProgressDialog.dismiss();
				}
			}
			@Override
			public void onAddressSearchBegin() {
				mAddressSearchView.hideSoftKeyboard();
				mProgressDialog = ProgressDialog.show(MapSearchActivity.this,
						getString(R.string.please_wait), getString(R.string.searching,
								mAddressSearchView.getText()), true, false);
			}
		});

		return super.onCreateOptionsMenu(menu);
	}

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	switch (item.getItemId()) {
    		case android.R.id.home:
    			startActivity(PubListActivity.createIntent(this));
    			break;
    		case R.id.menu_viewmode:
    			mMapView.setSatellite(!mMapView.isSatellite());
    			break;
    		case R.id.menu_mylocation:
    			mLocationOverlay.runOnFirstFix(new Runnable() {
    				public void run() {
    					mController.stopAnimation(false);
    					mController.animateTo(mLocationOverlay.getMyLocation());
    				}
    			});
    			break;
    		case R.id.menu_search:
    			mAddressSearchView.requestFocus();
    			mAddressSearchView.showSoftKeyboard();
    			break;
    	}

    	return super.onOptionsItemSelected(item);
    }

	/**
	 * Navigates to address on the map.
	 * @param address Address we want to navigate to.
	 */
	private void navigateTo(Address address) {
		if (!address.hasLatitude() || !address.hasLongitude()) {
			return;
		}
		GeoPoint geoPoint = new GeoPoint((int) (address.getLatitude() * 1e6),
				(int) (address.getLongitude() * 1e6));
		mController.animateTo(geoPoint);
		// TODO
		// get pubs in area
	}

	public static Intent createIntent(Context context) {
		Intent intent = new Intent(context, MapSearchActivity.class);
		intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
		return intent;
	}
}
